using System;

namespace Bookvar.ObjectModel.Actions
{
    /// <summary>
    /// Adds a new topic in the mind map.
    /// </summary>
    /// <remarks>
    /// If the position of the topic is not set it will be added in the end.
    /// </remarks>
    public class AddTopicAction : TopicActionBase
    {
        private int? insertIndex;
        private Topic parent;

        /// <summary>
        /// Initializes a new instance of the <see cref="AddTopicAction"/> class.
        /// </summary>
        public AddTopicAction()
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="AddTopicAction"/> class.
        /// </summary>
        /// <param name="newTopic">The new topic.</param>
        /// <exception cref="ArgumentNullException"> if <paramref name="newTopic"/> is null.
        /// </exception>
        public AddTopicAction( Topic newTopic ) : base( newTopic )
        {
        }

        /// <summary>
        /// Gets or sets the parent of the new topic. This is a mandatory property for this action.
        /// </summary>
        /// <value>The parent of the new topic.</value>
        /// <exception cref="ArgumentNullException">if <paramref name="value"/> is null.</exception>
        public Topic Parent
        {
            get { return parent; }
            set
            {
                if ( value == null ) throw new ArgumentNullException( "value" );

                parent = value;
            }
        }

        /// <summary>
        /// Gets the index at which the topic will be added. If the insert index is not provided 
        /// the topic will be inserted in the end.
        /// </summary>
        /// <value>The index at which the topic will be added.</value>
        public int? InsertIndex
        {
            get { return insertIndex; }
            set { insertIndex = value; }
        }

        /// <summary>
        /// Executes (or redoes) the action: adds the topic to the specified parent's subtopics.
        /// </summary>
        /// <exception cref="InvalidOperationException">
        /// if <see cref="Parent"/> or <see cref="Topic"/> is not set;
        /// or if the action is already executed.
        /// </exception>
        public override void Execute()
        {
            base.Execute();

            if ( Parent == null )
            {
                throw new InvalidOperationException( "Parent property must be set." );
            }

            int index = insertIndex ?? Parent.SubTopics.Count;
            Parent.SubTopics.Insert( index, Topic );
        }

        /// <summary>
        /// Undoes the action.
        /// </summary>
        /// <exception cref="System.InvalidOperationException">if called before the action is executed.</exception>
        public override void Undo()
        {
            base.Undo();

            if ( Parent == null )
            {
                throw new InvalidOperationException( "Parent property must be set." );
            }

            parent.SubTopics.Remove( Topic );
        }
    }
}
